package com.ml.loan.common.lock;

import java.util.concurrent.TimeUnit;

/**
 * 分布式锁封装
 *
 * @author czx
 */
public interface DistributedLock {

    /**
     * 获取锁，如果获取不成功则一直等待直到lock被获取
     *
     * @param key       锁的key
     * @param leaseTime 加锁时间，到期自动解锁（如果leaseTime为-1，则保持锁定直到显式解锁）
     * @param unit      {@code leaseTime} 参数的时间单位
     * @param isFair    是否公平锁
     * @return 锁对象
     * @throws Exception
     */
    ZLock lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;

    default ZLock lock(String key, long leaseTime, TimeUnit unit) throws Exception {
        return this.lock(key, leaseTime, unit, false);
    }

    default ZLock lock(String key, boolean isFair) throws Exception {
        return this.lock(key, 10, TimeUnit.SECONDS, isFair);
    }

    default ZLock lock(String key) throws Exception {
        return this.lock(key, 10, TimeUnit.SECONDS, false);
    }


    /**
     * 尝试获取锁，如果锁不可用则等待waitTime后放弃
     *
     * @param key       锁的业务key
     * @param waitTime  获取锁的最大尝试时间
     * @param leaseTime 加锁的时间，到期自动解锁（如果leaseTime为-1，则保持锁定直到显式解锁）
     * @param unit      {@code waitTime} 和 {@code leaseTime} 参数的时间单位
     * @param isFair    否公平锁
     * @return 锁对象，如果获取锁失败则为null
     * @throws Exception
     */
    ZLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;

    default ZLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception {
        return this.tryLock(key, waitTime, leaseTime, unit, false);
    }

    default ZLock tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception {
        return this.tryLock(key, waitTime, 10, unit, isFair);
    }

    default ZLock tryLock(String key, long waitTime, TimeUnit unit) throws Exception {
        return this.tryLock(key, waitTime, 10, unit, false);
    }

    /**
     * 释放锁
     *
     * @param lock
     * @throws Exception
     */
    void unlock(Object lock) throws Exception;

    /**
     * 释放锁
     *
     * @param lock 抽象锁对象
     * @throws Exception
     */
    default void unlock(ZLock lock) throws Exception {
        if (lock != null) {
            this.unlock(lock.getLock());
        }
    }

}
